package com.zkh.myutils.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtils {
	
	/**
	 * 将日期字符串格式化成另一种格式的日期字符串
	 * @param source
	 * @param format
	 * @param toFormat
	 * @return
	 */
	public static String convertDate(String source, String format, String toFormat){
		//首先转换成Date对象，再将Date对象转换成指定格式的字符串
		return getString(getDate(source, format), toFormat);
	}
	
	/**
	 * 按指定格式获取当前时间
	 * @param format 时间格式
	 * @return
	 */
	public static String now(String format){
		return getString(format);
	}
	
	
	/**
	 * 按格式获取日期。如指定yyyyMMdd，可将当前日期格式化为只含年月日的日期
	 * @param format 日期格式
	 * @return
	 */
	public static Date getDate(String format) {
		return getDate(new Date(), format);
	}
	
	/**
	 * 按格式获取日期。如指定new Date()和yyyyMMdd，可将当前日期格式化为只含年月日的日期
	 * @param source 时间源
	 * @param format 日期格式
	 * @return
	 */
	public static Date getDate(Date source, String format) {
		return getDate(getString(source, format));
	}

	/**
	 * 将字符串解析成java.util.Date对象
	 * @param source 要解析的字符串
	 * @param format 字符串模式
	 * @return java.util.Date对象
	 */
	public static Date getDate(String source, String format){
		//按给定的pattern创建SimpleDateFormat对象
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		//解析字符串
		try {
			return sdf.parse(source);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 字符串转日期
	 * @param dateString 日期字符串，格式为：yyyyMMdd[HHmmssSSS]，“年月日”必须，“时分秒毫秒”可省略。
	 * @return
	 */
	public static Date getDateByString(String dateString) {
		//长度
		int len = dateString.length();
		//小于8
		if(len<8) {
			throw new IllegalArgumentException();
		}
		//日历
		Calendar calendar = Calendar.getInstance();
		//年月日
		calendar.set(Calendar.YEAR, Integer.parseInt(dateString.substring(0, 4)));
		calendar.set(Calendar.MONTH, Integer.parseInt(dateString.substring(4, 6))-1);
		calendar.set(Calendar.DATE, Integer.parseInt(dateString.substring(6, 8)));
		//时分秒毫秒
		calendar.set(Calendar.HOUR_OF_DAY, len<10 ? 0 : Integer.parseInt(dateString.substring(8, 10)));
		calendar.set(Calendar.MINUTE, len<12 ? 0 : Integer.parseInt(dateString.substring(10, 12)));
		calendar.set(Calendar.SECOND, len<14 ? 0 : Integer.parseInt(dateString.substring(12, 14)));
		calendar.set(Calendar.MILLISECOND, len<17 ? 0 : Integer.parseInt(dateString.substring(14)));
		//返回
		return calendar.getTime();
	}
	
	/**
	 * 格式化当前日期
	 * @param format 日期格式
	 * @return
	 */
	public static String getString(String format) {
		return getString(new Date(), format);
	}
	
	/**
	 * 格式化日期
	 * @param source 指定日期
	 * @param format 日期格式
	 * @return
	 */
	public static String getString(Date source, String format) {
		//按给定的pattern创建SimpleDateFormat对象
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		//返回格式化后的字符串
		return sdf.format(source);
	}
	
	/**
	 * 将Date对象格式化
	 * @param timestamp 时间戳（毫秒）
	 * @param format 转换格式
	 * @return 格式化后的字符串
	 */
	public static String getString(long timestamp, String format){
		//返回格式化后的字符串
		return getString(new Date(timestamp), format);
	}
	
	/**
	 * 获取与当前时间相加或相减后的Date对象
	 * @param typeAdds 依次按类型、差值排列的数据，如：[类型, 差值, 类型, 差值...] <br />
	 * <b>如果参数为奇数个，最后一个参数将被自动忽略。</b>
	 * @return
	 */
	public static Date getAddDate(int... typeAdds) {
		return getAddDate(new Date(), typeAdds);
	}
	
	/**
	 * 获取与当前时间相加或相减后的Date对象
	 * @param from 时间源
	 * @param typeAdds 依次按类型、差值排列的数据，如：[类型, 差值, 类型, 差值...] <br />
	 * <b>如果参数为奇数个，最后一个参数将被自动忽略。</b>
	 * @return
	 */
	public static Date getAddDate(Date from, int... typeAdds) {
		//Calendar对象
		Calendar calendar = Calendar.getInstance();
		//设置时间源
		calendar.setTime(from);
		//遍历类型差值
		for(int i=0,len=typeAdds.length;i<len;i+=2){
			if(i+1<=len-1){
				calendar.add(typeAdds[i], typeAdds[i+1]);
			}
		}
		//按格式返回数据
		return calendar.getTime();
	}
	
	/**
	 * 获取与当前时间相加或相减后的时间字符串
	 * @param format 时间显示格式
	 * @param typeAdds 依次按类型、差值排列的数据，如：[类型, 差值, 类型, 差值...] <br />
	 * <b>如果参数为奇数个，最后一个参数将被自动忽略。</b>
	 * @return
	 */
	public static String getAddDate(String format, int... typeAdds) {
		return getAddDate(new Date(), format, typeAdds);
	}
	
	/**
	 * 获取与指定时间源相加或相减后的时间字符串
	 * @param from 指定时间源
	 * @param format 时间显示格式
	 * @param typeDiffers 依次按类型、差值排列的数据，如：[类型, 差值, 类型, 差值...] <br />
	 * <b>如果参数为奇数个，最后一个参数将被自动忽略。</b>
	 * @return
	 */
	public static String getAddDate(Date from, String format, int... typeAdds) {
		return getString(getAddDate(from, typeAdds), format);
	}
	
	/**
	 * 格式化时间差。<b>1个月按30天计算</b>
	 * @param differtime 时间差（秒）
	 * @return 将指定时间差转换为“xx年xx月xx天xx小时xx分xx秒”的格式。转换长度取决于传递值。
	 */
	public static String formatDiff(int differtime) {
		return formatDiff(differtime * 1000L);
	}
	
	/**
	 * 格式化时间差。<b>1个月按30天计算</b>
	 * @param differtime 时间差（毫秒）
	 * @return 将指定时间差转换为“xx年xx月xx天xx小时xx分xx秒”的格式。转换长度取决于传递值。
	 */
	public static String formatDiff(long differtime) {
		//格式
		String[] ft = {"秒", "分", "小时", "天", "月", "年"};
		int[] times = {60, 60, 24, 30, 12};
		//格式化数据
		String fmt = "";
		//分别判断
		if(differtime<1000) {
			fmt = "不足1秒";
		}else{
			//转为秒
			differtime/=1000;
			//计位
			int bit = 0;
			//大于0
			while(differtime>0 && bit<6) {
				//求余
				int mod = (int) (bit==5 ? differtime : (differtime%times[bit]));
				//求商并赋值
				differtime /= (bit==5 ? 1 : times[bit]);
				//保存
				fmt = mod + ft[bit] + fmt;
				//位数加1
				bit++;
			}
		}
		//返回格式化数据
		return fmt;
	}
}
